package adc.app.ui.wicket;

import java.io.Serializable;

import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.extensions.markup.html.tree.table.IColumn;
import org.apache.wicket.extensions.markup.html.tree.table.TreeTable;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.ResourceModel;

public abstract class TreeTablePanel extends Panel {

    private static final long serialVersionUID = 1L;

    private static final String ID_TREE_TABLE =  "tt";

    public interface IAddNodeCallback extends Serializable {
        void addNode(AjaxRequestTarget target);
    }

    public interface IDeleteNodeCallback extends Serializable {
        boolean deleteNode(AjaxRequestTarget target, TreeNode node);
    }
    
    public interface IEditNodeCallback extends Serializable {
        void editNode(AjaxRequestTarget target, TreeNode node);
    }
    
    private IAddNodeCallback addNodeCallback;
    private IEditNodeCallback editNodeCallback;
    private IDeleteNodeCallback deleteNodeCallback;
    
    private final TreeTable tt;

    public TreeTablePanel(String id, TreeNode root, IColumn[] cols) {
        super(id);
        tt = new TreeTable(ID_TREE_TABLE, new DefaultTreeModel(root), cols);
        add(tt);
        add(new AddNodeButton("add", "addLbl"));
        add(new EditNodeButton("edit", "editLbl"));
        add(new DeleteNodeButton("delete", "deleteLbl"));
    }

    public IAddNodeCallback getAddNodeCallback() {
        return addNodeCallback;
    }

    public TreeTablePanel setAddNodeCallback(IAddNodeCallback addNodeCallback) {
        this.addNodeCallback = addNodeCallback;
        return this;
    }

    public IEditNodeCallback getEditNodeCallback() {
        return editNodeCallback;
    }
    public TreeTablePanel setEditNodeCallback(IEditNodeCallback editNodeCallback) {
        this.editNodeCallback = editNodeCallback;
        return this;
    }
    public IDeleteNodeCallback getDeleteNodeCallback() {
        return deleteNodeCallback;
    }
    public TreeTablePanel setDeleteNodeCallback(IDeleteNodeCallback deleteNodeCallback) {
        this.deleteNodeCallback = deleteNodeCallback;
        return this;
    }

    public void updateTree(AjaxRequestTarget target) {
        tt.updateTree(target);
    }

    private static final class AddNodeButton extends AjaxLink<Object> {

        private static final long serialVersionUID = 1L;

        public AddNodeButton(String id, String labelId) {
            super(id);
            add(new Label(labelId, new ResourceModel(IMsgs.ADD)));
        }

        @Override public void onClick(AjaxRequestTarget target) {
            TreeTablePanel ttp = this.findParent(TreeTablePanel.class);
            if (ttp.addNodeCallback != null) {
                ttp.addNodeCallback.addNode(target);
            }
        }
    }

    private static final class EditNodeButton extends AjaxLink<Object>  {

        private static final long serialVersionUID = 1L;

        public EditNodeButton(String id, String labelId) {
            super(id);
            add(new Label(labelId, new ResourceModel(IMsgs.EDIT)));
        }

        @Override public void onClick(AjaxRequestTarget target) {
            TreeTablePanel ttp = this.findParent(TreeTablePanel.class);
            if (ttp.editNodeCallback != null && !ttp.tt.getTreeState().getSelectedNodes().isEmpty()) {
                TreeNode selNode = (TreeNode) ttp.tt.getTreeState().getSelectedNodes().iterator().next();
                ttp.editNodeCallback.editNode(target, selNode);
            }
        }
    }
    private static final class DeleteNodeButton extends AjaxLink<Object>  {

        private static final long serialVersionUID = 1L;

        public DeleteNodeButton(String id, String labelId) {
            super(id);
            add(new Label(labelId, new ResourceModel(IMsgs.DELETE)));
        }

        @Override public void onClick(AjaxRequestTarget target) {
            TreeTablePanel ttp = this.findParent(TreeTablePanel.class);
            if (ttp.deleteNodeCallback != null && !ttp.tt.getTreeState().getSelectedNodes().isEmpty()) {
                TreeNode selNode = (TreeNode) ttp.tt.getTreeState().getSelectedNodes().iterator().next();
                if (ttp.deleteNodeCallback.deleteNode(target, selNode)) {
                    ((DefaultTreeModel)ttp.tt.getModel().getObject()).nodesWereRemoved(
                            selNode.getParent(), new int[] {selNode.getParent().getIndex(selNode)}, 
                            new Object[]{selNode});
                    ttp.tt.updateTree(target);
                }
            }
        }
    }

}
